package chooongg.base.utils

import java.io.BufferedReader
import java.io.DataOutputStream
import java.io.IOException
import java.io.InputStreamReader

object ShellUtils {

    private val LINE_SEP = System.getProperty("line.separator")

    /**
     * 执行命令
     *
     * @param command         命令行
     * @param isRooted        是否使用Root权限
     * @param isNeedResultMsg 是否需要回掉消息
     */
    @JvmOverloads
    fun execCmd(
        command: String,
        isRooted: Boolean,
        isNeedResultMsg: Boolean = true
    ): CommandResult {
        return execCmd(arrayOf(command), isRooted, isNeedResultMsg)
    }

    /**
     * 执行命令
     *
     * @param commands        命令行
     * @param isRooted        是否使用Root权限
     * @param isNeedResultMsg 是否需要回掉消息
     */
    @JvmOverloads
    fun execCmd(
        commands: List<String>?,
        isRooted: Boolean,
        isNeedResultMsg: Boolean = true
    ): CommandResult {
        return execCmd(commands?.toTypedArray(), isRooted, isNeedResultMsg)
    }

    /**
     * 执行命令
     *
     * @param commands        命令行
     * @param isRooted        是否使用Root权限
     * @param isNeedResultMsg 是否需要回掉消息
     */
    @JvmOverloads
    fun execCmd(
        commands: Array<String>?,
        isRooted: Boolean,
        isNeedResultMsg: Boolean = true
    ): CommandResult {
        var result = -1
        if (commands == null || commands.isEmpty()) {
            return CommandResult(result, null, null)
        }
        var process: Process? = null
        var successResult: BufferedReader? = null
        var errorResult: BufferedReader? = null
        var successMsg: StringBuilder? = null
        var errorMsg: StringBuilder? = null
        var os: DataOutputStream? = null
        try {
            process = Runtime.getRuntime().exec(if (isRooted) "su" else "sh")
            os = DataOutputStream(process!!.outputStream)
            for (command in commands) {
                os.write(command.toByteArray())
                os.writeBytes(LINE_SEP!!)
                os.flush()
            }
            os.writeBytes("exit$LINE_SEP")
            os.flush()
            result = process.waitFor()
            if (isNeedResultMsg) {
                successMsg = StringBuilder()
                errorMsg = StringBuilder()
                successResult = BufferedReader(
                    InputStreamReader(
                        process.inputStream,
                        "UTF-8"
                    )
                )
                errorResult = BufferedReader(
                    InputStreamReader(
                        process.errorStream,
                        "UTF-8"
                    )
                )
                var line: String?
                if (successResult.readLine().apply { line = this } != null) {
                    successMsg.append(line)
                    while (successResult.readLine().apply { line = this } != null) {
                        successMsg.append(LINE_SEP).append(line)
                    }
                }
                if (errorResult.readLine().apply { line = this } != null) {
                    errorMsg.append(line)
                    while (errorResult.readLine().apply { line = this } != null) {
                        errorMsg.append(LINE_SEP).append(line)
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                os?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
            try {
                successResult?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
            try {
                errorResult?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
            process?.destroy()
        }
        return CommandResult(result, successMsg?.toString(), errorMsg?.toString())
    }


    /**
     * 命令结果Bean
     */
    class CommandResult(var result: Int, var successMsg: String?, var errorMsg: String?)

}